package com.wfh.easychat.websocket;

import com.wfh.easychat.common.ErrorCode;
import com.wfh.easychat.exception.BusinessException;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.timeout.IdleStateHandler;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

/**
 * @Title: NettyStart
 * @Author wangfenghuan
 * @Package com.wfh.easychat.websocket
 * @Date 2025/10/5 13:24
 * @description:
 */
@Slf4j
@Component
public class NettyStart {

    private final EventLoopGroup bossGroup = new NioEventLoopGroup(1);

    private final EventLoopGroup workGroup = new NioEventLoopGroup();

    private volatile Channel serverChannel;

    @PostConstruct
    public void start(){
        Thread.startVirtualThread(() -> {
            try {
                ServerBootstrap serverBootstrap = new ServerBootstrap();
                serverBootstrap.group(bossGroup, workGroup);
                serverBootstrap.channel(NioServerSocketChannel.class)
                        .handler(new LoggingHandler(LogLevel.INFO))
                        .childHandler(new ChannelInitializer<>() {
                            @Override
                            protected void initChannel(Channel channel) throws Exception {
                                ChannelPipeline pipeline = channel.pipeline();
                                // 对http协议的支持，使用http的解码器，编码器
                                pipeline.addLast(new HttpServerCodec());
                                // 聚合解码，保证接受的http请求的完整性
                                pipeline.addLast(new HttpObjectAggregator(1024 * 64));
                                // 心跳
                                pipeline.addLast(new IdleStateHandler(6, 0, 0, TimeUnit.SECONDS));
                                pipeline.addLast(new TimeOutHandler());
                                // 将http协议升级为ws协议
                                pipeline.addLast(new WebSocketServerProtocolHandler("/ws", null, true, 1024 * 64, true,true, 10000L));
                                pipeline.addLast(new WebSocketHandler());
                            }
                        });
                ChannelFuture channelFuture = serverBootstrap.bind(8081).sync();
                this.serverChannel = channelFuture.channel();
                log.info("netty启动成功！！！");
                serverChannel.closeFuture().sync();
                log.info("关闭！");
            } catch (InterruptedException e) {
                log.info("netty启动失败：{}", e.getMessage());
                throw new BusinessException(ErrorCode.SYSTEM_ERROR, e.getMessage());
            }
        });

    }

    @PreDestroy
    public void stop(){
        log.info("⚠️正在关闭netty websocket服务");
        // 关闭serverchannel，会关闭所有的childchannel关闭
        if (serverChannel != null){
            // 等待关闭完成
            serverChannel.close().syncUninterruptibly();
        }

        log.info("✅netty websocket关闭完成");
    }
}
